package legumes.client.ui.otherboxes.order;

import java.util.Map;

import legumes.client.evt.customer.CustomerOrderChangedEvent;
import legumes.client.evt.manager.EventBusManager;
import legumes.client.resources.PNResources;
import legumes.client.ui.widgets.utils.Formatters;
import legumes.shared.domain.OrderPart;
import legumes.shared.domain.OrderPartProductItem;
import legumes.shared.domain.Unit;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.DOM;
import com.smartgwt.client.data.Record;
import com.smartgwt.client.types.Alignment;
import com.smartgwt.client.types.ListGridFieldType;
import com.smartgwt.client.util.BooleanCallback;
import com.smartgwt.client.util.SC;
import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.form.fields.ComboBoxItem;
import com.smartgwt.client.widgets.form.fields.FormItem;
import com.smartgwt.client.widgets.form.fields.TextItem;
import com.smartgwt.client.widgets.grid.CellFormatter;
import com.smartgwt.client.widgets.grid.HeaderSpan;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.ListGridField;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import com.smartgwt.client.widgets.grid.ListGridSummaryField;
import com.smartgwt.client.widgets.grid.RecordSummaryFunction;
import com.smartgwt.client.widgets.grid.events.EditCompleteEvent;
import com.smartgwt.client.widgets.grid.events.EditCompleteHandler;
import com.smartgwt.client.widgets.grid.events.EditorEnterEvent;
import com.smartgwt.client.widgets.grid.events.EditorEnterHandler;
import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
import com.smartgwt.client.widgets.layout.VLayout;

public class CustomerOrderPanel extends VLayout {

	private ListGrid listGrid;
	private ListGridField userQuantityUnitField;
	private ListGridField userQuantityField;

	private OrderPart op;
	
	public CustomerOrderPanel() {
		super();
		setWidth100();
		
		setShowEdges(false);
		
		setMembersMargin(5);  
        setLayoutMargin(10); 
        
		build();
	}
	
	public void initData(OrderPart op_){
		op = op_;
		displaySellSessionForCustomer();
	}
	
	protected void displaySellSessionForCustomer() {
    	
		int i=0;
		ListGridRecord [] records = new ListGridRecord[op.getOrderPartProductItems().size()];
		for (OrderPartProductItem p : op.getOrderPartProductItems()) {
			try{
				ListGridRecord record = new ListGridRecord();
				record.setAttribute("prix", p.getOnSaleProduct().getPrice().getAmount() );
				record.setAttribute("libelle", p.getOnSaleProduct().getProduct().getName() );
				record.setAttribute("quantite", p.getOnSaleProduct().getPrice().getQuantity().getValue() );
				record.setAttribute("unit", p.getOnSaleProduct().getPrice().getQuantity().getUnitAsEnum().getDisplayName() );
				if(p!= null && p.getOnSaleProduct().getProduct() != null && p.getOnSaleProduct().getProduct().getProductVariety() != null
						&& p.getOnSaleProduct().getProduct().getProductVariety().getProductCategory() != null &&
								p.getOnSaleProduct().getProduct().getProductVariety().getProductCategory().getName() != null ){
					record.setAttribute("categorie", p.getOnSaleProduct().getProduct().getProductVariety().getProductCategory().getName() );
					
				} else {
					record.setAttribute("categorie", "Autres");
				}
				
				record.setAttribute("userQuantite", p.getQuantity().getValue() );
				record.setAttribute("userQuantiteUnit", p.getQuantity().getUnitAsEnum().getDisplayName() );
				
				records[i]= record;
				i++;
			} catch (NullPointerException e_) {
				GWT.log("Err on displaySellSessionForCustomer ", e_);
			}
		}
		listGrid.setRecords(records);
	}
	
	private float computeTotalFromRecord(Record record_){
		float total = 0.0f;
        try{
        	float coef = 1.0f;
        	String unit = record_.getAttribute("unit");
        	if(unit.equalsIgnoreCase(Unit.KG.name()) 
        			&& record_.getAttribute("userQuantiteUnit").equalsIgnoreCase(Unit.G.name())){
        		coef = 1/1000f;
        	} else if (unit.equalsIgnoreCase(Unit.G.name()) 
        			&& record_.getAttribute("userQuantiteUnit").equalsIgnoreCase(Unit.KG.name())){
        		coef = 1000f;
        	}
        	
            total = record_.getAttributeAsFloat("prix") 
            		* record_.getAttributeAsFloat("userQuantite")
        			* coef
        			/ record_.getAttributeAsFloat("quantite");
        } catch(Exception e_){
            
        }
        return total;
	}
	private void build(){
		listGrid = new ListGrid();
        
        ListGridField categoryField = new ListGridField("categorie");  
        categoryField.setCanEdit(false);
        categoryField.setHidden(true);
        
        ListGridField libelleField = new ListGridField("libelle", "Produit", 100);  
        libelleField.setCanEdit(false);
        
        userQuantityField = new ListGridField("userQuantite", "Quantit&eacute;", 50);
        userQuantityField.setAlign(Alignment.RIGHT);
        userQuantityField.setType(ListGridFieldType.FLOAT);
        
        userQuantityUnitField = new ListGridField("userQuantiteUnit", "Unit&eacute;", 50);
        userQuantityUnitField.setAlign(Alignment.LEFT);
        //TODO set value MAP
        //The value map depends of the current record
        
        ListGridField priceField = new ListGridField("prix", "Prix", 150); 
        priceField.setCanEdit(false);
        priceField.setAlign(Alignment.RIGHT);  
        priceField.setCellFormatter(new CellFormatter() {  
            public String format(Object value_, ListGridRecord record_, int rowNum, int colNum) {  
            	if(value_ == null) return null;  
                String valueStr = Formatters.formatPrice( value_, true);
                 
                String unit = record_.getAttribute("unit");
                float quantite = record_.getAttributeAsFloat("quantite");
                
                if(unit == null){
                	unit = "";
                }
                return valueStr == null ? "" : 
                	quantite == 1 ?
                			valueStr + " &frasl; " + unit :
                			valueStr + " &frasl; " + quantite + " " + unit ;
                
            }  
        });
  
        ListGridSummaryField totalField = new ListGridSummaryField("total", "Total", 50);
        totalField.setType(ListGridFieldType.SUMMARY);
        totalField.setCanEdit(false);
        totalField.setAlign(Alignment.RIGHT);          
        totalField.setRecordSummaryFunction(new RecordSummaryFunction(){

            @Override
            public Object getSummaryValue(Record record_, ListGridField[] fields_, ListGridField summaryField_) {
                return new Float( computeTotalFromRecord(record_) );
            }
            
        });
        
        totalField.setCellFormatter(new CellFormatter() {
            
            public String format(Object value, ListGridRecord record, int rowNum, int colNum) {  
                return value == null?null:Formatters.formatPrice(value, true);
            }  
        });  
        
        ListGridField editRowField = new ListGridField("editRow", "&nbsp;", 30);
        editRowField.setCanEdit(false);
        editRowField.setAlign(Alignment.CENTER);  
        editRowField.setType(ListGridFieldType.ICON);
        editRowField.setCellIcon(PNResources.INSTANCE.editIcon().getURL());
        editRowField.addRecordClickHandler(new RecordClickHandler() {
			
			@Override
			public void onRecordClick(RecordClickEvent event_) {
				listGrid.startEditing(listGrid.getRecordIndex(event_.getRecord()), 2, true);
			}
		});
        
        ListGridField deleteRowField = new ListGridField("deleteRow", "&nbsp;", 30);
        deleteRowField.setCanEdit(false);
        deleteRowField.setAlign(Alignment.CENTER);  
        deleteRowField.setType(ListGridFieldType.ICON);
        deleteRowField.setCellIcon(PNResources.INSTANCE.deleteIcon().getURL());
        deleteRowField.addRecordClickHandler(new RecordClickHandler() {
			
			@Override
			public void onRecordClick(final RecordClickEvent event_) {
				final OrderPartProductItem oppi = op.findOrderPartProductItemFor(event_.getRecord().getAttribute("libelle"));
				final String pName = oppi.getOnSaleProduct().getProduct().getName();
				
				SC.ask("Suppression du produit '" + pName + "' ?",
						"Supprimer le produit '" + pName + "' de votre commande ?", new BooleanCallback() {

					@Override
					public void execute(Boolean value) {
						if(value){
							op.getOrderPartProductItems().remove(oppi);
							
							//Inform the total
							EventBusManager.getInstance().getEventBus().fireEvent(
			            			new CustomerOrderChangedEvent(false, computeTotalFromRecord(event_.getRecord()) ));
							
							//Remove the flag from the slate product
							DOM.getElementById("shoppingChartGreen." + oppi.getOnSaleProduct().getProduct().getName()).removeClassName("productInChartGreen");
							
							listGrid.removeData(event_.getRecord());
						}
					}
					
				});
			}
		});
         
        listGrid.setWidth100();
        listGrid.setHeight("*");
        listGrid.setHeaderHeight(40); 
        listGrid.setShowAllRecords(true);
        listGrid.setCanEdit(true);  
        listGrid.setGroupByField("categorie");  
        listGrid.setGroupStartOpen("all");
        listGrid.setEmptyMessage("Aucun produit");
        
        listGrid.setHeaderSpans(  
                new HeaderSpan("Les l&eacute;gumes au choix", new String[]{"libelle", "prix"}),  
                new HeaderSpan("Votre commande", new String[]{"userQuantite", "userQuantiteUnit", "total", "editRow", "deleteRow"}) );  
  
        listGrid.setFields(categoryField, libelleField, priceField, userQuantityField,  userQuantityUnitField, totalField, editRowField, deleteRowField);  
          
        listGrid.addEditorEnterHandler(new EditorEnterHandler() {
			
			@Override
			public void onEditorEnter(EditorEnterEvent event) {
				FormItem fi = null;
				
				ListGridRecord lgr = listGrid.getRecord(event.getRowNum());
				String quantiteUnit = lgr.getAttribute("unit");
            	if(quantiteUnit != null &&
            		(	quantiteUnit.equalsIgnoreCase(Unit.G.name())
            		|| 	quantiteUnit.equalsIgnoreCase(Unit.KG.name()))
            	){
            		ComboBoxItem cbi = new ComboBoxItem();
                	cbi.setValueMap(Unit.G.name(), Unit.KG.name());
                	cbi.setValue(quantiteUnit);
                	cbi.setDefaultValue(quantiteUnit);
                	fi = cbi;
            	} else {
            		TextItem ti = new TextItem(quantiteUnit);
            		ti.setDisabled(true);
            		fi = ti;
            	}
            	
            	userQuantityUnitField.setEditorType(fi);  
                userQuantityUnitField.setCanEdit(true);
                userQuantityField.setCanEdit(true);
            	listGrid.refreshFields();
			}
		});
        
        listGrid.addEditCompleteHandler(new EditCompleteHandler() {
			private float computeOldTotal(Record r){
				float quantite = r.getAttributeAsFloat("quantite");
				String unit = r.getAttribute("unit");
				float price = r.getAttributeAsFloat("prix");
				
				
				Float userQuantite = r.getAttributeAsFloat("userQuantite");
				if( userQuantite == null ){
					userQuantite = 0f;
				}
				String userUnit = r.getAttribute("userQuantiteUnit");
				if( userUnit == null ){
					userUnit = unit;
				}
				float coef = 1.0f;
            	if(unit.equalsIgnoreCase(Unit.KG.name()) 
            			&& userUnit.equalsIgnoreCase(Unit.G.name())){
            		coef = 1/1000f;
            	} else if (unit.equalsIgnoreCase(Unit.G.name()) 
            			&& userUnit.equalsIgnoreCase(Unit.KG.name())){
            		coef = 1000f;
            	}
            	float total = userQuantite*price*coef / quantite;
            	
            	return total;
			}
			
			
			@Override
			public void onEditComplete(EditCompleteEvent event) {
				//TODO SMA => Should manage event.getOldRecord() to send event for TOTAL CMDE
				//We take the old total
				//We compute the new total with the quantity
				Record oldRecord = event.getOldRecord();
				float oldTotal = computeOldTotal(oldRecord);
				
				String productName = oldRecord.getAttribute("libelle");
				float quantite = oldRecord.getAttributeAsFloat("quantite");
				String unit = oldRecord.getAttribute("unit");
				float price = oldRecord.getAttributeAsFloat("prix");
				
				Map<String, Object> newValues = (Map<String, Object>)event.getNewValues();
				
				//UserQuantity or userQuantityUnit should have changed
				if( newValues != null ){
					// ### USER QUANTITY
					Float newUserQuantite = null;
					try{
						newUserQuantite = new Float(newValues.get("userQuantite").toString());
	            	} catch(Exception e_){
	            		
	            	} finally {
	            		if( newUserQuantite == null ){
		            		//Not edited, take the old one
		            		try{
		            			newUserQuantite = oldRecord.getAttributeAsFloat("userQuantite");
		            			if( newUserQuantite == null ){
		            				newUserQuantite = quantite;
		            			}
		            		} catch(Exception e2_){
		            			newUserQuantite = quantite;
		            		}
	            		}
	            	}
	            	
					// ### USER QUANTITY UNIT
	            	String newUserQuantiteUnitStr = null;
					try{
	            		newUserQuantiteUnitStr = newValues.get("userQuantiteUnit").toString();
	            	} catch(Exception e_){
	            	} finally{
	            		if(newUserQuantiteUnitStr==null){
		            		//Not edited, take the old one
		            		try{
		            			newUserQuantiteUnitStr = oldRecord.getAttribute("userQuantiteUnit");
		            			if(newUserQuantiteUnitStr==null){
		            				newUserQuantiteUnitStr = unit;
		            			}
		            		} catch(Exception e2_){
		            			newUserQuantiteUnitStr = unit;
		            		}
	            		}
	            	}

	            	Unit newUserQuantiteUnit = Unit.fromDisplayName(newUserQuantiteUnitStr);
	            	//We convert the user quantity unit to the vendor display unit
	            	float coef = 1.0f;
	            	if(unit.equalsIgnoreCase(Unit.KG.name()) 
	            			&& newUserQuantiteUnit.equals(Unit.G)){
	            		coef = 1/1000f;
	            	} else if (unit.equalsIgnoreCase(Unit.G.name()) 
	            			&& newUserQuantiteUnit.equals(Unit.KG)){
	            		coef = 1000f;
	            	}
	            	OrderPartProductItem oppi = op.findOrderPartProductItemFor(productName);
	            	oppi.getQuantity().setUnitAsEnum(newUserQuantiteUnit);
	            	oppi.getQuantity().setValue(newUserQuantite);
	            	
					float newTotal = newUserQuantite*price*coef / quantite;
					float totalDif = newTotal - oldTotal;
					
					EventBusManager.getInstance().getEventBus().fireEvent(
	            			new CustomerOrderChangedEvent(totalDif>0, Math.abs(totalDif) ));
							
				}
			}
		});
        
        Label lab = new Label();
        lab.setContents("<h3>Hors Panier</h3>");
        lab.setHeight(20);
        lab.setWidth100();
        lab.setLayoutAlign(Alignment.CENTER);
        setLayoutAlign(Alignment.CENTER);
        setMembers(lab, listGrid);
	}
}
